package global

import (
	"database/sql"
	"db2s/limit"
	"os"
	"sync"
	"time"
)

var MyMap sync.Mutex
var MyWait sync.WaitGroup

// input prepare struct
type (
	EncryptionProperties struct {
		LockFuncName   string   `json:"lock"`
		UnLockFuncName string   `json:"unlock"`
		ColumnSlice    []string `json:"column"`
		EsaColumnSeq   map[int]int
	}
	PartitionOptions struct {
		PartitionGather       []string `json:"pg"`
		IgnorePartitionGather []string `json:"ipg"`
	}
	SchemaTableSubOptions struct {
		ForceIndex      string               `json:"forceIndex"`
		WhereSql        string               `json:"whereSql"`
		PX              string               `json:"px"`
		WhereAdd        string               `json:"whereAdd"`
		SecColumn       EncryptionProperties `json:"sec"`
		PartitionGather PartitionOptions     `json:"partition"`
		InsertIgnore    string               `json:"ignore"`
	}
	SchemaTableParameterInput struct {
		TableList       map[string] /*库名*/ int                 /*库名目标端值*/
		TableMap        map[string] /*映射前schema+table*/ string /*映射后的schema+table*/
		TableSubOptions map[string]SchemaTableSubOptions
	}
	//SchemaTableSubOptionsMerge struct {
	//	ForceIndexMerge map[string]string            `json:"forceIndex"`
	//	WhereSql        map[string]string            `json:"whereSql"`
	//	WhereAdd        map[string]string            `json:"whereAdd"`
	//	SecColumn       SecureEncryptedColumnOptions `json:"sec"`
	//	PartitionGather PartitionOptions             `json:"partition"`
	//}
)
type (
	IndexColumn struct {
		Schema        string `json:"databaseName"`
		Table         string `json:"tableName"`  //--
		IndexName     string `json:"indexName"`  //--
		ColumnType    string `json:"columnType"` //--
		ColumnSeq     string `json:"columnSeq"`  //--
		ColumnName    string `json:"columnName"` //--
		IndexSeq      string `json:"indexSeq"`
		Null          string `json:"null"`
		SubPart       string `json:"subPart"` //前缀索引长度
		AutoIncrement string `json:"autoIncrement"`
		Cardinality   string `json:"cardinality"`   //--
		ColumnKey     string `json:"columnKey"`     //--判断是普通索引，还是唯一索引，还是普通索引
		IndexCategory string `json:"indexCategory"` //--
	}
	IndexMerge struct {
		Schema           string                   `json:"schema"`
		Table            string                   `json:"table"`
		IndexColumn      map[string][]IndexColumn `json:"indexColumn"`
		IndexType        map[string]string        `json:"indexType"`
		IndexColumnSeq   map[string][]string      `json:"indexColumnSeq"`
		OrderByIndexName []string                 //用于索引名的正序排列
	}

	IndexSelection struct {
		Schema           string
		Table            string
		IndexColumn      []IndexColumn       //索引列详细信息
		IndexType        string              //索引类型，主键、唯一、普通
		IndexColumnSeq   map[string][]string //索引列序号
		IndexName        string              //索引列名
		IndexColumnType  []string            //选中的索引列的数据类型
		IndexCardinality uint64              //索引的离散度，表示的是行数，需要计算
	}
	SingleIndexResult struct {
		Type           string
		Name           string   `json:"name"`
		Cardinality    int64    `json:"cardinality"`
		Column         []string `json:"column"`
		AllIndexColumn []string `json:"allIndexColumn"`
	}
	IndexPrioritySort struct {
		Primary   []SingleIndexResult `json:"primary"`
		UniqueKey []SingleIndexResult `json:"uniqueKey"`
		Key       []SingleIndexResult `json:"key"`
	}
	IndexColumnSumGroup struct {
		Single   IndexPrioritySort
		Multiple IndexPrioritySort
	}
	ConvertDefaultValue struct {
		OldValue string `json:"oldValue"` //默认值的原始值
		NewValue string `json:"newValue"`
		Format   string `json:"format"` //数据类型的数据格式，多用于时间类型
	}
	ConvertColumnMeta struct {
		GroupType      string //聚合类型：type(precision,scale)
		Type           string //判断是数值类型、时间类型、文本类型、字符串类型，二进制
		ShowSize       any    //数据类型显示长度
		MaxSize        any    //显示当前数据类型的最大程度
		DataLength     int    //字符串占用的长度
		DataLengthUnit string //数据类型中的长度值是按字符算还是字节算，可选值：char(字符),byte（字节）
		FixedSwitch    bool   //表示是否定长 true 表示定长，false不定长
		Symbol         bool   //表示是有符号还是无符号的,可选值：true 表示无符号，false表示有符号
		Format         string //数据类型的数据格式，多用于时间类型
	}
	TableMeta struct {
		DatabaseName        string `json:"databaseName"`
		TableName           string `json:"tableName"`
		ColumnName          string `json:"columnName"`
		ColumnType          string `json:"columnType"` //原始的数据类型，不带长度的
		ColumnSeq           string `json:"columnSeq"`
		IsNull              string `json:"isNull"` //
		Charset             string `json:"charset"`
		CollationName       string `json:"collationName"`
		ColumnComment       string `json:"columnComment"`
		ColumnDefault       string `json:"columnDefault"`
		DataType            string `json:"dataType"` //处理过的数据类型，带长度的
		DataLength          string `json:"dataLength"`
		CharLength          string `json:"charLength"`
		DataPrecision       string `json:"dataPrecision"`
		DataScale           string `json:"dataScale"`
		Invisible           bool   `json:"invisible"`
		AutoIncrement       bool
		ConvertColumnType   ConvertColumnMeta
		ConvertDefaultValue ConvertDefaultValue
	}

	ObjectMapList struct {
		Schema  string `json:"schema"`  // schema 映射前的值
		SchemaM string `json:"schemaM"` //schema 映射后的值
		Table   string `json:"table"`   //table 映射前的值
		TableM  string `json:"tableM"`  //table 映射后的值
	}
	UseTableMetadata struct {
		Src map[string][]TableMeta `json:"src"` //源端表的元数据信息
		Dst map[string][]TableMeta `json:"dst"` //目标端表的元数据信息
	}
	UseIndex struct {
		UseIndexColumn []string `json:"useIndexColumn"` //使用的索引列名
		UseIndexName   string   `json:"useIndexName"`   //使用的索引名
		UseIndexType   string   `json:"useIndexType"`   //使用索引的类型，主键、唯一、普通索引
	}
	TableParameterInput struct {
		TableList            map[string] /*库名*/ int                                                        /*库名目标端值*/
		TableMap             map[string] /*映射前schema+table*/ string                                        /*映射后的schema+table*/
		TableGroup           map[string] /*附加类型forceIndex whereAdd whereSql*/ map[string] /*库名+表名*/ string /*索引名*/
		ForceIndex           map[string]string
		WhereAdd             map[string]string
		WhereSql             map[string]string
		PX                   map[string]string
		EncryptionProperties map[string]EncryptionProperties
	}
	TableMapStrconv struct {
		TableMap   map[string]string
		Schema     string
		Table      any
		ResultType string /*schema返回库名，table表示返回表名，all返回schema+table*/
	}
	TableMetaGather struct {
		Schema  string
		Table   string
		MSchema string
		MTable  string
		SourceM []TableMeta
		DestM   []TableMeta
	}
)

// sync use struct
type (
	StructPlan struct {
		Switch    bool
		CheckMod  string
		TaskStart *int64
		TaskEnd   *int64
	}
	LoadPlan struct {
		CheckMod               string
		CheckRows              SyncCheckCount
		WriteFileN             *os.File
		WriteFileName          string
		WriteTableMeta         *os.File
		WriteTableMetaFileName string
		ReadTableMeta          *os.File
		ReadFileName           string
		ReadTableFileName      string
		ReadFileN              *os.File
	}
)

type (
	// TLoad 终端结果输出表结构
	TLoad struct {
		Seq        string `json:"seq"`
		Schema     string `json:"schema"`
		Table      string `json:"table"`
		IndexType  string `json:"indexType"`
		IndexCol   string `json:"indexColumn"`
		CheckMode  string `json:"mode"`       //模式
		SyncSum    *int64 `json:"syncSum"`    //表的实际行数
		SelectRows *int64 `json:"selectRows"` //源端查询装填
		InsertRows *int64 `json:"insertRows"` //目标端写入状态
		SyncStatus *int64 //同步状态   0为正常，-1为异常
		SyncInfo   string `json:"syncInfo"` //同步信息，主要记录error信息
	}
	TCount struct {
		Seq          string `json:"seq"`
		Schema       string `json:"schema"`
		Table        string `json:"table"`
		CheckMode    string `json:"mode"`
		IndexType    string `json:"indexType"`
		IndexCol     string `json:"indexColumn"`
		SourceNumber *int64 `json:"srcCount"`
		DestNumber   *int64 `json:"dstCount"`
		CheckResult  string `json:"chkStat"` //校验状态
	}
	Trows struct {
		Seq          string `json:"seq"`
		Schema       string `json:"schema"`
		Table        string `json:"table"`
		CheckMode    string `json:"mode"`
		Options      string `json:"options"`
		IndexType    string `json:"indexType"`
		IndexCol     string `json:"indexCol"`
		RowsSum      *int64 `json:"rowsSum"`
		SourceNumber *int64 `json:"srcCount"`
		DestNumber   *int64 `json:"dstCount"`
		InsertSum    *int64 `json:"insertSum"`
		UpdateSum    *int64 `json:"updateSum"`
		DeleteSum    *int64 `json:"DeleteSum"`
		Status       *int64 `json:"status"`
		CheckResult  string `json:"chkStat"`
	}
	TStruct struct {
		Seq         string `json:"seq"`
		Schema      string `json:"schema"`
		Table       string `json:"object"`
		Role        string `json:"role"`
		CheckMode   string `json:"checkMode"`
		IssueType   string `json:"issue Type"`
		Status      *int64
		DataFixType string `json:"fix Type"`
		CheckResult string `json:"checkStat"`
		ExecObject  string `json:"execObject"`
		ExecResult  string `json:"execStat"`
	}
	TObject struct {
		Seq         int    `json:"seq"`
		Schema      string `json:"schema"`
		Table       string `json:"object"`
		Role        string `json:"role"`
		CheckMode   string `json:"checkMode"`
		IssueType   string `json:"issue Type"`
		Status      *int64
		DataFixType string `json:"fix Type"`
		CheckResult string `json:"checkStat"`
		ExecObject  string `json:"execObject"`
		ExecResult  string `json:"execStat"`
	}
)
type (
	XStructMissTable struct {
		Schema  string `json:"schema"`
		Table   string `json:"table"`
		Missing string `json:"missing source"`
	}
	XObjectMissTable struct {
		Schema  string `json:"schema"`
		Table   string `json:"object"`
		Missing string `json:"missing source"`
	}
	XLoadSheetTail struct {
		Seq        string `json:"任务序号"`
		Schema     string `json:"库名"`
		Table      string `json:"表名"`
		SyncSum    *int64 `json:"任务启动时源端获取记录数"` //表的实际行数
		SelectRows *int64 `json:"迁移过程中获取行数"`    //源端查询装填
		InsertRows *int64 `json:"迁移过程中写入行数"`    //目标端写入状态
		SyncStatus string `json:"任务状态"`         //同步状态   0为正常，-1为异常
		TableCost  string `json:"单表迁移耗时(s)"`
		Comment    string `json:"备注"` //主要描述错误信息的记录
	}
	XCountSheetTail struct {
		Seq        string `json:"任务序号"`
		Schema     string `json:"库名"`
		Table      string `json:"表名"`
		SyncSum    *int64 `json:"任务启动时源端获取记录数"` //表的实际行数
		SelectRows *int64 `json:"迁移过程中获取行数"`    //源端查询装填
		InsertRows *int64 `json:"迁移过程中写入行数"`    //目标端写入状态
		SyncStatus string `json:"任务状态"`         //同步状态   0为正常，-1为异常
		TableCost  string `json:"单表迁移耗时(s)"`
		Comment    string `json:"备注"` //主要描述错误信息的记录
	}
	XRowsSheetTail struct {
		Seq                    string `json:"任务序号"`
		Schema                 string `json:"库名"`
		Table                  string `json:"表名"`
		IndexType              string `json:"条件类型"`  //条件类型
		SrcRows                *int64 `json:"源端行数"`  //源端查询总行数
		DstRows                *int64 `json:"目标端行数"` //目标端查询总行数
		AbnormalRows           *int64 `json:"差异行总数"`
		InsertRows             *int64 `json:"修复insert数"`
		DeleteRows             *int64 `json:"修复delete数"`
		AbnormalTypeSum        *int64 `json:"差异类型总数"`
		CheckStatus            string `json:"校验状态"` //同步状态   0为正常，-1为异常
		AbnormalTypeProportion string `json:"数据差异分类/占比"`
		TableCost              string `json:"单表校验耗时(s)"`
		Comment                string `json:"备注"`
	}
	XLoadSheetName struct {
		Terminal  string `json:"db2s_terminal"`
		Result    string `json:"load_result"`
		MissTable string `json:"missTable"`
	}
	XCountSheetName struct {
		Terminal  string `json:"terminal"`
		Result    string `json:"count_result"`
		MissTable string `json:"missTable"`
	}
	XRowsSheetName struct {
		Terminal  string `json:"terminal"`
		Result    string `json:"rows_result"`
		MissTable string `json:"missTable"`
	}
	XStruct struct {
		SheetTail MetaTitleSheetName
	}
)
type (
	EFunc struct {
		FuncName func(event string,f any) (r any) `json:"funcName"`
		Params   any                 `json:"params"`
	}
)
type (
	// TPod 终端输出表结构
	TPod struct {
		TableName string
		TableMiss bool
		Seq       int    //task打印的任务序号
		Mode      string //用于区分是那个功能模块
		Task      TTask
		Sync      TSync
		Load      TLoad
		Count     TCount
		Rows      Trows
		Struct    TStruct
		Object    TObject
		HotSql    Thotsql
		Samp      Tsamp
	}
	// XlsTail 输出表结构
	XlsTail struct {
		Struct XStruct
	}
)

// 接口传参
type (
	//GeneralInsertPrefixSqlP GeneralInsertPrefixSql函数入参
	GeneralInsertPrefixSqlP struct {
		LogSeq           int64
		Schema           string
		Table            string
		TableType        string   //普通表还是partition表，"single"为单表，"partition"为分区表
		PartitionName    string   //partition Name
		PartitionId      string   //cluster PartitionId
		InsertColumn     []string //insert插入列名
		PlaceholderValue []string //用于prepare 预解析sql的占位符

	}
	//ApplySqlP ApplySql函数入参
	ApplySqlP struct {
		LogSeq             int64
		DB                 map[string]*sql.DB
		TableType          string //普通表还是partition表，"single"为单表，"partition"为分区表
		ShardName          string
		PartitionShardName string
		ApplySqlGather     []*string
	}
	//FixInsertSqlGeneralP FixInsertSqlGeneralP函数入参
	FixInsertSqlGeneralP struct {
		LogSeq   int64
		RowsData string
		ColData  []map[string]string
	}
	//IndexColumnStartPartValueP IndexColumnStartPartValue函数入参
	IndexColumnStartPartValueP struct {
		LogSeq                    int64
		ActiveType                string //行为类型，是src还是dst
		Schema                    string
		Table                     string
		IndexColumn               []string
		IndexColumnType           []string //索引列的数据类型
		LimitPagination           int64
		WhereAdd                  string
		WhereSql                  string
		NullConstraint            string
		Error                     string
		IndexColumnLeftDirection  []map[string]string //包含columnName、columnDataLeft、querySymbolLeft
		IndexColumnRightDirection []map[string]string //包含columnName、columnDataRight、querySymbolRight
		TableColumn               []TableMeta
		Esa                       EncryptionProperties
		RowsActiveMapList         map[string]string //行数据差异映射处理
		DB                        map[string]*sql.DB
		OutputColumnType          string //输出index||all，默认为索引列,all表示查询所有列，index表示查询索引列
		QueryIdentity             string //查询身份
		TaskSeq                   int64
		FirstLine                 bool
		SqlExecStopTime           time.Duration
		ShardName                 string
		PartitionId               string
		SqlMode                   bool
		DataType                  string
		Ws, Wc                    []string
	}
)

type MqProductCustomerSendMsgSum struct {
	ProductMsg               *int64 //生产者消息
	CustomerMsg              *int64 //消费者消息
	ProductObject            *int64 //生产者对象
	CustomerObject           *int64 //消费者对象
	ProductSendMsgFinishMark *int64 //消费端结束状态
}
type (
	MqProductCustomerMonitorMessage struct {
		FirstMsg                        MqProductCustomerSendMsgSum
		SecondMsg                       MqProductCustomerSendMsgSum
		MqProductSeq                    *int64 //生产者信息
		MqCustomerSeq                   *int64 //消费者数据记录
		MqFirstProductSendMsgFinishMark *int64 //一级消息发送完成状态标记
		ProductMessage                  chan map[string][]string
		MqStartTiming                   *int64
		MqLevelProductSend              *int64 //level 1生成的总数
		MqLevelCustomerReceive          *int64
		ObjectSum                       *int64
	}
	TableAllColumnInfoS struct {
		SColumnInfo    []TableMeta //表的所有列信息
		DColumnInfo    []TableMeta //表的所有列信息
		Schema         string
		Table          string
		IndexColumnSeq map[string]string
		ColumnSeq      map[string]string
		MapTable       map[string]string
		IndexType      string
		IndexColumn    []string
		SShardName     string
		DShardName     string
	}
	ReadOptimizer struct {
		IndexColumn      []string                                        //check table index column
		IndexColumnSeq   map[string] /*column seq + column name*/ string //check table index column Seq
		IndexColumnType  string                                          //check table index type
		ChunkStartSource string                                          //schedule task type  value:src,dst,all
		IndexName        string                                          //index name
		IndexCardinality string                                          //index  Cardinality
		ChunkSum         int64
		Thread           *int64
	}
	TableMetaS struct {
		Part PartMetaMarge
	}
	Object struct {
		TaskSeq         int    //表校验序号
		ObjectLogSeq    int64  //表对象的日志号
		TableMiss       bool   //表是否存在
		Schema, Table   string //check schema Name and check table Name
		MSchema, MTable string //map check schema name and check table name
		RowsLimit       int    //限制表的查询/迁移行数
		Role            string
		Meta            TableMetaS
		Input           StartPartConfigInputP
		TableColData    TableAllColumnInfoS //table column info
		Esa             EncryptionProperties
	}
	TableStatus struct {
		LogSeq           int64 //log seq
		ErrEnd           *int64
		ErrInfo          string //错误信息
		SubTaskBeginTime int64
	}
	DBInstanceConfig struct {
		LowPositionConn   int64
		CurryPositionConn map[string]map[string]int64
		HighPositionConn  map[string]map[string]int64
	}
	TableSpeedLimit struct {
		ReadSum        *int64
		WriteSum       *int64
		ReadParallel   *int64
		WriteParallel  *int64
		ReadExecCount  *int64
		Status         *int64 //0 表示不限速，1表示限速
		WriteExecCount *int64
		ReadAvgTime    *uint64 //read data exec sum time(ms)
		WriteAvgTime   *uint64 //write data exec sum time(ms)
		InstanceConfig DBInstanceConfig
		SpeedLimit     *limit.RateLimiter
	}
)
type IndexStatisticsS struct {
	Schema           string `json:"databaseName"`
	Table            string `json:"tableName"`
	UniqueType       string `json:"uniqueType"`
	IndexName        string `json:"indexName"`
	IndexSeq         string `json:"columnSeq"`
	IndexColumn      string `json:"columnName"`
	PreFix           string `json:"prefix"`
	IndexCardinality string `json:"cardinality"`
}
type (
	LengthLimitInput struct {
		ObjectType string //库名、表名、列名、表备注，列备注，
	}
)

type (
	PartitionSumReturnResult struct {
		Type string
		Sum  int64
	}
	ObjectExistReturnResult struct {
		BaseResult ReturnBaseResult
		Result     bool
	}
	ObjectNameReturnResult struct {
		BaseResult ReturnBaseResult
		Result     []string
	}
	CountReturnResult struct {
		Result     uint64
		BaseResult ReturnBaseResult
	}
	RowsReturnResult struct {
		Result     uint64
		BaseResult ReturnBaseResult
	}
	AllReturnResult struct {
		Result     []TableMeta
		BaseResult ReturnBaseResult
	}
	StartPartReturnResult struct {
		Result     map[string]any
		BaseResult ReturnBaseResult
	}
)

// gis 结构体
type (
	// Point 定义 POINT 结构体
	Point struct {
		X   string `json:"X"`
		Y   string `json:"Y"`
		Z   string `json:"Z"`
		RID string `json:"RID"`
	}
)
